﻿using System.IO;
using Lidgren.Network;
using Network;
using Network.Messages.FileTranser;

namespace Providers.FileTransfer.Server
{
	public class StreamingServer
	{
        public static int Channel { get; } = 1;

        private FileStream _mInputStream;
		private int _mSentOffset;
		private readonly int _mChunkLen;
		private readonly byte[] _mTmpBuffer;
		private readonly NetConnection _mConnection;
	    private readonly NetworkPeer _network;
	    private readonly string _CilentName;
	    private readonly uint _number;
	    private uint _sendIndex;
	    private readonly string _sourceFile;
        public StreamingServer(NetworkPeer network, NetConnection conn, string fileName,string cilentFileName,uint number)
        {
            _network = network;
            _mConnection = conn;
            _CilentName = cilentFileName;
            _number = number;
            _mInputStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
            _mChunkLen = _mConnection.Peer.Configuration.MaximumTransmissionUnit - 20;
			_mTmpBuffer = new byte[_mChunkLen];
			_mSentOffset = 0;
            _sendIndex = 0;
            _sourceFile = fileName;
        }

	    public bool FlagComplete = false;
		public void Heartbeat()
		{
			if (_mInputStream == null)
				return;

			int windowSize, freeWindowSlots;
			_mConnection.GetSendQueueInfo(NetDeliveryMethod.ReliableOrdered, 1, out windowSize, out freeWindowSlots);
			if (freeWindowSlots > 0)
			{
				// send another part of the file!
				long remaining = _mInputStream.Length - _mSentOffset;
				int sendBytes = (remaining > _mChunkLen ? _mChunkLen : (int)remaining);

				// just assume we can read the whole thing in one Read()
				_mInputStream.Read(_mTmpBuffer, 0, sendBytes);
                
				if (_mSentOffset == 0)
				{
				    ResponseBeginCopyFileMessage message = new ResponseBeginCopyFileMessage()
				    {
				        FilePath = _CilentName,
                        FlagZip = false,
                        Number = _number,
                        Length = (ulong)_mInputStream.Length,
                    };
				    _network.SendMessage(message, NetDeliveryMethod.ReliableOrdered, Channel, _mConnection);
				}

                ResponseCopyFileMessage copyFileMessage = new ResponseCopyFileMessage()
                {
                    Number = _number,
                    SendIndex = _sendIndex++,
                    ChunkLen = sendBytes,
                    TempBuffer = _mTmpBuffer,
                    
                };
                _network.SendMessage(copyFileMessage, NetDeliveryMethod.ReliableOrdered, Channel, _mConnection);

				_mSentOffset += sendBytes;

				//Program.Output("Sent " + _mSentOffset + "/" + _mInputStream.Length + " bytes to " + _mConnection);

                
				if (remaining - sendBytes <= 0)
				{
                    _mInputStream.Close();
					_mInputStream.Dispose();
					_mInputStream = null;
				    FlagComplete = true;
                    ResponseEndCopyFileMessage endCopyFileMessage = new ResponseEndCopyFileMessage()
                    {
                        Number = _number,
                        SourceFile = _sourceFile,
                        DestFile = _CilentName
                    };
                    _network.SendMessage(endCopyFileMessage, NetDeliveryMethod.ReliableOrdered, Channel, _mConnection);

                }
            }
		}
	}
}
